<template>
  <a-card :bordered="false" :headStyle="{ border: 'none' }">
    <a-spin :spinning="loading">
      <div class="app">
        <div class="app-wrap">
          <div class="app-left">
            <div class="avatar-wrap">
              <div>
                <a-avatar class="avatar" :size="150" :src="logo | imgURLFilter">
                  <a-spin :tip="$t('platformManagement.app.uploading')" :spinning="uploading">
                    <a-icon slot="indicator" type="loading" style="font-size: 24px" spin />
                  </a-spin>
                </a-avatar>
              </div>
              <a-upload
                v-if="baseInfoActive && info.type !== 1"
                name="file"
                :show-upload-list="false"
                accept="image/jpeg,image/png"
                :before-upload="beforeUpload"
                :customRequest="customRequest"
                @change="handleChange"
              >
                <a-button icon="upload">{{ $t('platformManagement.app.changeLogo') }}</a-button>
              </a-upload>
              <div v-if="uploadErrorTips" class="tips-error">{{ $t('platformManagement.app.uploadAppLogo') }}</div>
            </div>
          </div>
          <div class="app-middle">
            <div class="app-form">
              <a-form :form="baseInfoForm" :label-col="{ span: 4 }" :wrapper-col="{ span: 16 }">
                <a-form-item :label="$t('platformManagement.app.appName')">
                  <s-input
                    :disabled="info.type === 1 && info.type !== 'enable'"
                    v-if="baseInfoActive"
                    class="custom-input"
                    v-decorator="[
                      'name',
                      {
                        rules: [
                          {
                            required: true,
                            message: $t('common.emptyErr', {
                              name: $t('platformManagement.app.appName').toLowerCase()
                            }),
                            transform: value => value && value.trim()
                          }
                        ]
                      }
                    ]"
                    :spell-check="false"
                    :limit="128"
                    autocomplete="off"
                  />
                  <span v-else>{{ info.name }}</span>
                </a-form-item>
                <a-form-item :label="$t('platformManagement.app.visitUrl')" v-show="!info.embedded || canEdit">
                  <template v-if="baseInfoActive && canEdit">
                    <s-textarea
                      class="custom-input"
                      v-decorator="[
                        'visitUrl',
                        {
                          validateFirst: true,
                          rules: [
                            {
                              required: true,
                              whitespace: true,
                              message: $t('common.emptyErr', { name: $t('platformManagement.app.visitUrl') })
                            },
                            { pattern: isBasicUrl, message: '请输入正确的网站地址' },
                            { validator: validateUrl }
                          ]
                        }
                      ]"
                      :autoSize="{ minRows: 1, maxRows: 3 }"
                    />
                    <a :href="baseInfoForm.getFieldValue('visitUrl')" target="_blank" style="margin-left: 8px;">{{
                      $t('common.test')
                    }}</a>
                  </template>
                  <span v-else>{{ info.visitUrl }}</span>
                </a-form-item>
                <a-form-item v-if="info.type !== 1" :label="$t('platformManagement.app.setAppPosition')">
                  <a-radio-group v-if="baseInfoActive" v-decorator="['positionFlag']">
                    <a-radio-button value="dashboard_bussiness">
                      {{ $t(positionName['dashboard_bussiness']) }}
                    </a-radio-button>
                    <a-radio-button value="dashboard_basic">
                      {{ $t(positionName['dashboard_basic']) }}
                    </a-radio-button>
                    <a-radio-button value="dashboard_third">
                      {{ $t(positionName['dashboard_third']) }}
                    </a-radio-button>
                  </a-radio-group>
                  <span v-else>{{ $t(positionName[info.positionFlag]) }}</span>
                </a-form-item>
                <a-form-item :label="$t('platformManagement.app.appIntro')">
                  <s-textarea
                    :disabled="info.type === 1"
                    v-if="baseInfoActive"
                    class="custom-input"
                    v-decorator="[
                      'briefIntro',
                      {
                        rules: [
                          {
                            required: true,
                            message: $t('common.emptyErr', { name: $t('platformManagement.app.appIntro') }),
                            transform: value => value && value.trim()
                          }
                        ]
                      }
                    ]"
                  />
                  <span v-else>{{ info.briefIntro }}</span>
                </a-form-item>
              </a-form>
            </div>
            <a
              v-action:edit
              v-if="id && !baseInfoActive && canEdit"
              href="javascript:;"
              class="btn-edit-basic"
              @click="handleBaseInfoActive"
            >
              <a-icon type="edit" />
            </a>
          </div>
          <div class="app-right">
            <div class="app-actions-top">
              <template v-if="id && info && info.type !== 1">
                <span style="margin-right: 8px;">{{
                  info.status === 1 ? $t('common.opened') : $t('common.closed')
                }}</span>
                <a-switch
                  v-action:edit
                  slot="extra"
                  :checkedChildren="$t('common.open')"
                  :unCheckedChildren="$t('common.close')"
                  defaultChecked
                  :checked="info.status === 1"
                  :loading="switching"
                  @click="handleSwitch"
                />
              </template>
            </div>
            <div class="app-actions-bottom" v-if="baseInfoActive">
              <a-button @click="handleCancelBaseInfo">{{ $t('common.cancel') }}</a-button>
              <a-button
                type="primary"
                style="margin-left: 8px;"
                :loading="baseInfoConfirmLoading"
                @click="handleSubmitBaseInfo"
              >{{ $t('common.submit') }}</a-button
              >
            </div>
          </div>
        </div>
      </div>
      <template v-if="id">
        <a-divider />
        <div class="auth-info-wrap">
          <div class="auth-info-left">
            <a-form class="auth-form" :form="authInfoForm" :label-col="{ span: 4 }" :wrapper-col="{ span: 20 }">
              <a-form-item label="AppId">
                {{ info.appId }}
              </a-form-item>
              <a-form-item label="Secret">
                {{ secret }}
                <a-button v-if="authInfoActive" type="link" :loading="secretLoading" @click="resetSecret">{{
                  $t('common.reset')
                }}</a-button>
              </a-form-item>
              <a-form-item v-if="info.type !== 1" :label="$t('common.administrator')">
                <span class="tag" v-for="item in adminUsers" :key="item.id">
                  <a-icon type="user" />
                  {{ item.name }}
                </span>
                <a-button type="link" v-if="authInfoActive" @click="beforePickUser('user')">{{
                  $t('button.add')
                }}</a-button>
              </a-form-item>
              <a-form-item v-if="info.type !== 1" :label="$t('platformManagement.app.visibleRange')">
                <span class="tag" v-for="item in accessibleDtos" :key="`${item.id}${item.type}`">
                  <a-icon :type="item.type === 1 ? 'user' : 'team'" />
                  {{ item.name }}
                </span>
                <a-button v-if="authInfoActive" type="link" @click="beforePickUser('all')">{{
                  $t('button.add')
                }}</a-button>
              </a-form-item>
            </a-form>
            <a
              v-action:edit
              v-if="!authInfoActive"
              href="javascript:;"
              class="btn-edit-auth"
              @click="handleAuthInfoActive"
            >
              <a-icon type="edit" />
            </a>
          </div>
          <div class="auth-info-right">
            <div class="auth-info-actions" v-show="authInfoActive">
              <a-button @click="handleCancelAuthInfo">{{ $t('common.cancel') }}</a-button>
              <a-button
                type="primary"
                style="margin-left: 8px;"
                :loading="authInfoConfirmLoading"
                @click="handleConfirmAuthInfo"
              >{{ $t('common.submit') }}</a-button
              >
            </div>
          </div>
        </div>
      </template>
      <template
        v-if="
          id &&
            info.type === 2 &&
            (($hasRouteAuth('messageConfig') &&
            ($hasRouteAuth('appSysInfo') || $hasRouteAuth('appCompanyWxConfig') || $hasRouteAuth('appMailConfig'))) ||
            $hasRouteAuth('baseDataConfig'))
        "
      >
        <a-divider />
        <a-card
          v-if="$hasRouteAuth('baseDataConfig')"
          :hoverable="true"
          @click="handleDevelopConfig(id)"
          style="width:180px; display: inline-block; margin-right: 24px;"
        >
          <a-card-meta>
            <a slot="title">{{ $t('modules.menu.baseDataConfig') }}</a>
          </a-card-meta>
        </a-card>
        <a-card
          v-if="
            $hasRouteAuth('messageConfig') &&
              ($hasRouteAuth('appSysInfo') || $hasRouteAuth('appCompanyWxConfig') || $hasRouteAuth('appMailConfig'))
          "
          :hoverable="true"
          @click="handleMessageConfig(info.appId)"
          style="width:150px; display: inline-block; margin-right: 24px;"
        >
          <a-card-meta>
            <a slot="title">{{ $t('modules.menu.messageConfig') }}</a>
          </a-card-meta>
        </a-card>
      </template>
    </a-spin>
    <!-- 人员、部门选择 -->
    <user-picker
      ref="userPicker"
      :visible="userPickerVisible"
      :title="userPickerMode === 'all' ? '可见范围选择' : '管理员选择'"
      :mode="userPickerMode === 'all' ? ['member', 'party'] : ['member']"
      :defaultSelectedKeys="defaultSelectedKeys"
      @ok="handlePickerUserOk"
      @close="userPickerVisible = false"
    />
  </a-card>
</template>

<script>
import { SInput, STextarea, UserPicker } from '@/components'
import { uploadFile } from '@/api/common'
import { isBasicUrl } from '@/utils/regExp'
import {
  createApplication,
  updateApplication,
  readApplication,
  createSecret,
  updateeAppMore,
  updateApplicationStatus
} from '@/api/application'
const positionName = {
  dashboard_bussiness: 'modules.common.busiApp',
  dashboard_basic: 'menu.industrialModel',
  dashboard_third: 'modules.common.DevOperAndcenter'
}
export default {
  name: 'ApplicationItem',
  components: {
    SInput,
    STextarea,
    UserPicker
  },
  data () {
    return {
      positionName,
      isBasicUrl,
      loading: false,
      logo: '',
      uploading: false,
      uploadErrorTips: false,
      baseInfoForm: this.$form.createForm(this),
      authInfoForm: this.$form.createForm(this),
      id: null,
      info: {},
      switching: false,
      // 激活基础信息编辑区域
      baseInfoActive: false,
      baseInfoConfirmLoading: false,
      // 激活权限信息编辑区域
      authInfoActive: false,
      authInfoConfirmLoading: false,
      secretLoading: false,
      secret: null,
      adminUsers: [],
      accessibleDtos: [],
      userPickerVisible: false,
      // all 部门和人员 user 人员
      userPickerMode: ''
    }
  },
  mounted () {
    const { id } = this.$route.params
    if (id) {
      this.id = id
      this.getAppInfo()
    } else {
      this.baseInfoActive = true
      this.$nextTick(() => {
        this.baseInfoForm.setFieldsValue({
          positionFlag: 'dashboard_bussiness'
        })
      })
    }
  },
  computed: {
    defaultSelectedKeys () {
      if (this.userPickerMode === 'user') {
        return this.adminUsers.map(item => `member${item.id}`)
      } else if (this.userPickerMode === 'all') {
        return this.accessibleDtos.map(item => {
          return (item.type === 1 ? 'member' : 'party') + item.id
        })
      } else {
        return []
      }
    },
    canEdit () {
      if (this.info.type === 1) {
        return this.info.canEditVisitUrl
      } else {
        return true
      }
    }
  },
  methods: {
    // 获取应用详情
    async getAppInfo () {
      this.loading = true
      const res = await readApplication({ id: this.id })
      this.loading = false
      if (res.code === 'sso.ok') {
        this.info = res.data
        this.logo = res.data.logo
        this.secret = res.data.secretKey
        this.adminUsers = res.data.adminUsers
        this.accessibleDtos = res.data.accessibleDtos
      }
    },
    // 域名校验
    validateUrl (rule, value, callback) {
      if ((value && value.indexOf('127.0.0.1') > -1) || value.indexOf('localhost') > -1) {
        callback('请输入正确的地址')
      } else {
        callback()
      }
    },
    // 返回列表页面
    handleBack () {
      this.$router.back()
    },
    // 开启基本信息编辑
    handleBaseInfoActive () {
      const { name, visitUrl, briefIntro, positionFlag } = this.info
      this.baseInfoActive = true
      this.$nextTick(() => {
        this.baseInfoForm.setFieldsValue({
          name: name || '',
          visitUrl: visitUrl || '',
          briefIntro: briefIntro || '',
          positionFlag: positionFlag || 'dashboard_bussiness'
        })
      })
    },
    // 开启权限信息编辑
    handleAuthInfoActive () {
      this.authInfoActive = true
    },
    // 重置 Secret
    async resetSecret () {
      this.secretLoading = true
      const { appId } = this.info
      const res = await createSecret({ appId })
      this.secretLoading = false
      if (res.code === 'sso.ok') {
        this.secret = res.data
      }
    },
    beforeUpload (file) {
      const isLtSize = file.size / 1024 / 1024 < 5
      if (!isLtSize) {
        this.$message.error('图片大小不能超过 5MB!')
      }
      return isLtSize
    },
    handleChange (info) {
      const { status } = info.file
      if (status === 'uploading') {
        this.uploading = true
      } else if (status === 'done') {
        const { response } = info.file
        this.logo = response.data
        this.uploading = false
        // 校验时 Logo 未通过
        this.uploadErrorTips = false
      } else if (status === 'error') {
        this.uploading = true
      }
    },
    // 上传文件
    async customRequest ({ file, filename, onSuccess, onError }) {
      const formData = new FormData()
      formData.append(filename, file)
      const res = await uploadFile(formData)
      if (res.code === 'sso.ok') {
        onSuccess(res)
      } else {
        onError()
      }
    },
    // 新建应用、保存基础信息
    handleSubmitBaseInfo () {
      if (!this.logo) return (this.uploadErrorTips = true)

      const {
        baseInfoForm: { validateFields, getFieldsValue }
      } = this
      this.baseInfoConfirmLoading = true
      const req = getFieldsValue()
      let fieldNames = ['name', 'visitUrl', 'briefIntro', 'positionFlag']
      if (this.info.embedded || !this.baseInfoActive || (this.info.type === 1 && !this.info.canEditVisitUrl)) {
        fieldNames = ['name', 'briefIntro']
      }
      validateFields(fieldNames, async (errors, values) => {
        if (!errors) {
          for (const key in req) {
            if (['name', 'visitUrl', 'briefIntro'].includes(key)) {
              req[key] = req[key] ? req[key].trim() : ''
            }
          }

          if (this.id) {
            req.id = this.id
          }
          req.canEditVisitUrl = this.info.canEditVisitUrl
          // 应用 LOGO
          req.logo = this.logo
          try {
            const res = this.id ? await updateApplication(req) : await createApplication(req)
            this.baseInfoConfirmLoading = false
            if (res.code === 'sso.ok') {
              this.$message.success(res.message)

              // 新建应用后，配置权限信息
              if (!this.id) {
                // 闯将完成后，停留次页面，经一步配置权限信息
                this.info = res.data
                this.baseInfoActive = true
                this.id = res.data.id
                this.setAuthInfo()
                this.$router.replace({ params: { id: res.data.id } })
              } else {
                this.getAppInfo()
              }
              this.baseInfoActive = false
            }
          } catch (error) {
            this.baseInfoConfirmLoading = false
          }
        } else {
          this.baseInfoConfirmLoading = false
        }
      })
    },
    // 新建应用时，返回列表页，编辑时取消激活区域，还原数据
    handleCancelBaseInfo () {
      if (this.baseInfoConfirmLoading) return
      if (this.id) {
        this.baseInfoActive = false
        // 恢复数据
        this.logo = this.info.logo
      } else {
        this.handleBack()
      }
    },
    // 配置权限信息
    setAuthInfo () {
      const { secretKey, adminUsers, accessibleDtos } = this.info
      this.secret = secretKey
      this.adminUsers = adminUsers || []
      this.accessibleDtos = accessibleDtos || []
    },
    beforePickUser (type) {
      this.userPickerMode = type
      this.userPickerVisible = true
    },
    // 人员选择完成后的逻辑
    handlePickerUserOk (selectNodes) {
      const { memberList, partyList } = selectNodes
      if (this.userPickerMode === 'user') {
        this.adminUsers = memberList
      } else if ((this.userPickerMode = 'all')) {
        const users = memberList.map(item => ({
          name: item.name,
          id: item.id,
          type: 1
        }))
        const partys = partyList.map(item => ({
          name: item.name,
          id: item.id,
          type: 2
        }))
        this.accessibleDtos = [...users, ...partys]
      }

      this.$refs.userPicker.resetModal()
    },
    // 取消激活权限编辑区域
    handleCancelAuthInfo () {
      if (this.authInfoConfirmLoading) return
      this.authInfoActive = false
      // 恢复数据
      this.secret = this.info.secretKey
      this.adminUsers = this.info.adminUsers
      this.accessibleDtos = this.info.accessibleDtos
    },
    // 修改App 管理员、可见范围等信息
    async handleConfirmAuthInfo () {
      this.authInfoConfirmLoading = true
      const { appId } = this.info
      const req = {
        id: this.id,
        appId,
        secretKey: this.secret,
        adminUsers: this.adminUsers.map(item => ({ id: item.id })),
        accessibleDtos: this.accessibleDtos.map(item => ({ id: item.id, type: item.type }))
      }
      const res = await updateeAppMore(req)
      this.authInfoConfirmLoading = false
      if (res.code === 'sso.ok') {
        this.$message.success(res.message)
        this.authInfoActive = false
        this.getAppInfo()
      }
    },
    // 修改应用状态
    async handleSwitch (status) {
      this.switching = true
      const res = await updateApplicationStatus({
        id: this.id,
        status: Number(status)
      })
      this.switching = false
      if (res.code === 'sso.ok') {
        this.info = { ...this.info, status: Number(status) }
        this.$message.success(res.message)
      }
    },
    handleDevelopConfig (id) {
      this.$router.push({
        name: 'baseDataConfig',
        query: {
          id: id
        }
      })
    },

    handleMessageConfig (id) {
      this.$router.push({
        name: 'messageConfig',
        query: {
          id: id
        }
      })
    }
  }
}
</script>

<style lang="less" scoped>
.app-wrap {
  display: flex;

  .app-left {
    text-align: center;

    .avatar {
      margin-bottom: 10px;
    }

    .tips-error {
      margin-top: 4px;
      font-size: 14px;
      line-height: 1.5;
      color: #f5222d;
      transition: color 0.3s cubic-bezier(0.215, 0.61, 0.355, 1);
    }
  }

  .app-middle {
    flex: 1;
    position: relative;
    margin-right: 20px;
    .btn-edit-basic {
      position: absolute;
      top: 0;
      right: 0;
      font-size: 20px;
      display: none;
    }
    &:hover {
      .btn-edit-basic {
        display: inline-block;
      }
    }
  }

  .app-right {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    width: 200px;
    text-align: right;
  }
}
.auth-info-wrap {
  display: flex;
  align-items: flex-end;
  .auth-info-left {
    position: relative;
    flex: 1;

    .btn-edit-auth {
      position: absolute;
      top: 0;
      right: 0;
      font-size: 20px;
      display: none;
    }

    .tag {
      display: inline-block;
      padding: 6px 11px;
      margin-right: 5px;
      margin-bottom: 5px;
      border: 1px solid #d9d9d9;
      line-height: 1.5;
      border-radius: 4px;
    }

    &:hover {
      .btn-edit-auth {
        display: inline-block;
      }
    }
  }
  .auth-info-right {
    width: 160px;
  }
}
.custom-input {
  width: calc(100% - 40px);
  display: inline-block;
}
</style>
